import 'dart:async';
import 'dart:io';
import 'dart:ui';

import 'package:number_spark_flutter/config/ns_global_config.dart';
import 'package:number_spark_flutter/network/ns_api.dart';
import 'package:number_spark_flutter/network/ns_network_utils.dart';
import 'package:number_spark_flutter/utils/ns_md5_utils.dart';
import 'package:number_spark_flutter/utils/ns_user_utils.dart';
import 'package:flutter_udid/flutter_udid.dart';
import 'dart:ui' as ui;

/// 打点请求头key统一传参
class NSLogHeadersKey {
  static const String nsData = "data";
  static const String nsAfCampaign = "campaign";
  static const String nsUtmSource = "utm_source";
  static const String nsAfAdgroupId = "af_adgroup_id";
  static const String nsLogType = "log_type";
  static const String nsSubtype = "subtype";
  static const String nsAfAdset = "af_adset";
  static const String nsAfAdsetId = "af_adset_id";
  static const String nsUserId = "user_id";
  static const String nsPkg = "pkg";
  static const String nsChnId = "chn_id";
  static const String nsBehavior = "behavior";
  static const String nsDeviceId = "device-id";
  static const String nsAndroidId = "android_id";
  static const String nsAfStatus = "af_status";
  static const String nsAfAgency = "af_agency";
  static const String nsModel = "model";
  static const String nsPVer = "p_ver";
  static const String nsSecId = "sec_id";
  static const String nsAfChannel = "af_channel";
  static const String nsAfCampaignId = "campaign_id";
  static const String nsCountry = "country";
  static const String nssysLan = "sys_lan";
  static const String nsVer = "ver";
  static const String nsPlatform = "platform";
  static const String nsLanId = "lan_id";
}

/// 打点中所有涉及到的页面KEY
class NSLogPages {
  // key值（字符串）参考下面的埋点事件
  static const String nsLaunch = 'launch';
  static const String nsAppLogin = 'applelogin';
  static const String nsCreateorder = 'createorder';
  static const String nsEditAvatar = 'editavatar';
  static const String nsDeleteAccount = 'deleteaccount';
  static const String nsCustomer = 'customer';
  static const String nsReport = 'report';
  static const String nsBlock = 'block';
  static const String nsUserTerms = 'terms';
  static const String nsPrivacy = 'privacy';
  static const String nsPurchase = 'purchase';
  static const String nsLogout = 'logout';
  static const String nsQuickLogin = 'quicklogin';

  //tab页面
  static const String nsHome = 'home';
  static const String nsRecord = 'record';
  static const String nsMine = 'mine';

  static const String nsSingleGame = 'singleGame';
  static const String nsDoubleGame = 'doubleGame';
}

class NSLogReportUtils {
  NSLogReportUtils._();

  static const String _event = 'event';
  static const String _tm = 'tm';
  static const String _page = 'page';
  static const String _subPage = 'subPage';
  static const String _terPage = 'terPage';
  static const String _broadcasterId = 'broadcasterId';
  static const String _duration = 'duration';

  static void stat({String? page, String? subPage, String? terPage, String? broadcasterId, NSLogType logType = NSLogType.globalBehavior}) {
    var map = <String, dynamic>{};
    if (page != null) {
      map[_page] = page;
    }
    if (subPage != null) {
      map[_subPage] = subPage;
    }
    if (terPage != null) {
      map[_terPage] = terPage;
    }
    if (broadcasterId != null) {
      map[_broadcasterId] = broadcasterId;
    }
    map[_duration] = 0;
    map[_event] = 'pv';
    map[_tm] = DateTime.now().millisecondsSinceEpoch;

    // if (kDebugMode) {
    //   log('$map', name: 'LogPvMgr');
    // }
    NSLogManger().putLog(logType, map);
  }
}

/// 打点类型
enum NSLogType {
  globalBehavior('event', 'global_behavior', 'event'),
  clickEvent("event", "click", "event");

  final String logType;
  final String subType;
  final String behavior;

  const NSLogType(this.logType, this.subType, this.behavior);
}

// 打点管理
class NSLogManger {
  static final NSLogManger _instance = NSLogManger._internal();

  factory NSLogManger() {
    return _instance;
  }

  NSLogManger._internal();

  static const String tag = "LogManger"; // 日志标签
  static const int limitSize = 20; // 打点任务最多缓存长度
  static int _serialId = 0;

  // static String launcherId = HBCrypotUntil.hbToMd5('${DateTime.now().millisecondsSinceEpoch}${HBDeviceUntil().hbDeviceId}');
  final List<Map<String, dynamic>> cacheList = [];
  bool _isWaitingForSend = false; // 是否需要延迟上报

  /// 上报日志
  void putLog(NSLogType logType, Map<String, dynamic>? event) async {
    if (logType.logType.isEmpty || logType.subType.isEmpty || logType.behavior.isEmpty || event == null || event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = await _buildItemData(logType.logType, logType.subType, logType.behavior, event);
    cacheList.insert(0, itemData);
    sendDelayed();
  }

  /// 延时发送日志
  void sendDelayed() {
    if (_isWaitingForSend) {
      return;
    }
    _isWaitingForSend = true;
    Timer(const Duration(milliseconds: 2000), () {
      _isWaitingForSend = false;
      sendLog(false);
    });
  }

  /// 发日志打点
  void sendLog(bool forceUploadAll) {
    try {
      List<Map<String, dynamic>> sendList = [];
      if (cacheList.isEmpty) {
        return;
      } else if (cacheList.length >= limitSize && !forceUploadAll) {
        sendList.addAll(cacheList.sublist(0, limitSize));
        cacheList.removeRange(0, limitSize);
      } else {
        sendList.addAll(cacheList);
        cacheList.clear();
      }
      _doUpload(sendList, true);
    } catch (e) {
      // if (kDebugMode) {
      //   print(e);
      // }
    }
  }

  /// 立马发送日志
  void putLogRightNow(NSLogType logType, Map<String, dynamic>? event) async {
    if (logType.logType.isEmpty || logType.subType.isEmpty || logType.behavior.isEmpty || event == null || event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = await _buildItemData(logType.logType, logType.subType, logType.behavior, event);
    List<Map<String, dynamic>> list = [];
    list.add(itemData);

    _doUpload(list, false);
  }

  /// 执行上传
  Future<void> _doUpload(List<Map<String, dynamic>> sendList, bool isContinue) async {
    NSResponseData responseData = await NSApi.reportLog.post(sendList);
    if (responseData.isSuccess()) {
      if (isContinue) {
        sendDelayed();
      }
    }
  }

  Future<Map<String, dynamic>> _buildItemData(String logType, String subType, String behavior, Map<String, dynamic>? event) async {
    String platform = '';
    String model = '';
    if (Platform.isAndroid) {
      platform = 'Android';
      model = NSNetWorkUtils.config.model ?? '';
    } else if (Platform.isIOS) {
      platform = 'iOS';
      model = NSNetWorkUtils.config.model ?? '';
    }
    String deviceId = await FlutterUdid.udid;
    Map<String, dynamic> map = {};
    map[NSLogHeadersKey.nsData] = [event];
    map[NSLogHeadersKey.nsLogType] = logType;
    map[NSLogHeadersKey.nsSubtype] = subType;
    map[NSLogHeadersKey.nsBehavior] = behavior;
    map[NSLogHeadersKey.nsDeviceId] = deviceId;
    map[NSLogHeadersKey.nsUserId] = NSUserUtils.getId();
    map[NSLogHeadersKey.nsPkg] = NSGlobalConfig.packageInfo.packageName ?? '';
    map[NSLogHeadersKey.nsChnId] = '';
    map[NSLogHeadersKey.nsVer] = NSGlobalConfig.packageInfo.version ?? '';
    map[NSLogHeadersKey.nsPlatform] = platform;
    map[NSLogHeadersKey.nsModel] = model;
    map[NSLogHeadersKey.nsPVer] = NSGlobalConfig.packageInfo.buildNumber ?? '';
    map[NSLogHeadersKey.nsLanId] = NSMd5Util.generateMd5('${DateTime.now().millisecondsSinceEpoch}$deviceId');
    map[NSLogHeadersKey.nsSecId] = _serialId++;
    map[NSLogHeadersKey.nsLanId] = window.locale.languageCode;
    map[NSLogHeadersKey.nsCountry] = NSUserUtils.getUserInfo().country ?? '';
    return map;
  }
}
